package com.ruicar.afs.cloud.manage.costexempt.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruicar.afs.cloud.common.config.ContractFeginConfig;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.security.util.SecurityUtils;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.modules.contract.enums.*;
import com.ruicar.afs.cloud.manage.api.dto.BasicExpenseRecordDetailDto;
import com.ruicar.afs.cloud.manage.api.feign.info.BasicMainInfoFeign;
import com.ruicar.afs.cloud.manage.common.entity.ManageCostExempt;
import com.ruicar.afs.cloud.manage.common.entity.ManageCostExemptConfig;
import com.ruicar.afs.cloud.manage.common.entity.ManageCostExemptDetailed;
import com.ruicar.afs.cloud.manage.common.service.ManageCostExemptConfigService;
import com.ruicar.afs.cloud.manage.common.service.ManageCostExemptDetailedService;
import com.ruicar.afs.cloud.manage.common.service.ManageCostExemptService;
import com.ruicar.afs.cloud.manage.common.util.CreatCaseNoUtil;
import com.ruicar.afs.cloud.manage.costexempt.condition.CostExemptCondition;
import com.ruicar.afs.cloud.manage.costexempt.condition.CostExemptDetailedCondition;
import com.ruicar.afs.cloud.manage.costexempt.vo.CostExemptConfigVo;
import com.ruicar.afs.cloud.manage.costexempt.vo.CostExemptDetailedVo;
import com.ruicar.afs.cloud.manage.workflow.enums.NormalSubmitEnum;
import com.ruicar.afs.cloud.manage.workflow.enums.WorkflowTypeEnum;
import com.ruicar.afs.cloud.manage.workflow.processor.ApproveTaskProcessor;
import com.ruicar.afs.cloud.manage.workflow.processor.ContractWorkFlowSaveApproveInfoProcessor;
import com.ruicar.afs.cloud.manage.workflow.service.WorkflowSubmitService;
import com.ruicar.afs.cloud.manage.workflow.vo.TaskSubmitVO;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.request.StartFlowRequest;
import com.ruicar.afs.cloud.workflow.gwt.service.WorkflowService;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/*
 * @author: sang jian
 * @date: 2020/8/3 19:48
 * @description:
 */

@Slf4j
@RestController
@RequestMapping("/costExempt")
@AllArgsConstructor
public class CostExemptController {

    private final ManageCostExemptService manageCostExemptService;
    private final ManageCostExemptDetailedService manageCostExemptDetailedService;

    private final ContractWorkFlowSaveApproveInfoProcessor saveApproveInfoProcessor;
    private final WorkflowSubmitService workflowSubmitService;
    private final WorkflowService workflowService;
    private final ApproveTaskProcessor approveTaskProcessor;

    private final BasicMainInfoFeign basicMainInfoFeign;
    private ContractFeginConfig contractFeginConfig;
    private final ManageCostExemptConfigService manageCostExemptConfigService;


    @PostMapping("/getCostExemptListByCondition")
    @ApiOperation(value = "多条件分页获取豁免费用列表")
    public IResponse getCostExemptListByCondition(@RequestBody CostExemptDetailedCondition condition) {
        Page pages = new Page(condition.getPageNumber(), condition.getPageSize());
        IPage<CostExemptDetailedVo> list = manageCostExemptDetailedService.getCostExemptListByCondition(pages, condition);
        IPage page = list;
        page.setRecords(approveTaskProcessor.handle(page.getRecords()));
        return IResponse.success(list);
    }

    @PostMapping("/getCostExemptListByExemptId")
    @ApiOperation(value = "根据费用豁免总表id查询对应的费用豁免列表")
    public IResponse getCostExemptListByExemptId(@RequestBody CostExemptDetailedCondition condition) {
        Long exemptId = condition.getExemptId();
        Page pages = new Page(condition.getPageNumber(), condition.getPageSize());
        Page page = manageCostExemptDetailedService.page(pages, Wrappers.<ManageCostExemptDetailed>query().lambda()
                .eq(ManageCostExemptDetailed::getExemptId, exemptId));
        ManageCostExempt costExempt = manageCostExemptService.getById(exemptId);
        List<CostExemptDetailedVo> vos = new ArrayList<>();
        if(page.getRecords().size() > 0 ){
            for (ManageCostExemptDetailed detailed : (List<ManageCostExemptDetailed>)page.getRecords() ){
                CostExemptDetailedVo costExemptDetailedVo = new CostExemptDetailedVo();
                BeanUtils.copyProperties(detailed,costExemptDetailedVo);
                costExemptDetailedVo.setStatus(costExempt.getStatus());
                costExemptDetailedVo.setCostType(detailed.getCostType().toString());
                vos.add(costExemptDetailedVo);
            }
        }
        page.setRecords(vos);
        return IResponse.success(page);
    }


    @PostMapping("/saveCostExemptList")
    @ApiOperation(value = "保存费用豁免清单(不走工作流,直接生效)")
    @Transactional
    public IResponse saveCostExemptList(@RequestBody List<CostExemptDetailedCondition> conditions) {
        //先汇总保存,然后再分别保存到明细表
        List<CostExemptDetailedCondition> manageCostExemptDetailedList = conditions;

        int size = manageCostExemptDetailedList.size();
        if (manageCostExemptDetailedList.size() > 0) {
            for (int i = size - 1; i >= 0; i--) {
                if (manageCostExemptDetailedList.get(i).getExemptionAmt().compareTo(BigDecimal.ZERO) == 0) {
                    manageCostExemptDetailedList.remove(i);
                }
            }
        }

        if (manageCostExemptDetailedList.size() > 0) {
            //合同号
            String contractNo = manageCostExemptDetailedList.get(0).getContractNo();
            String custName = manageCostExemptDetailedList.get(0).getCustName();
            String caseNo = CreatCaseNoUtil.GeneratorCaseNo(ContractBusinessEnum.costExempt);

            BigDecimal totalCosts = new BigDecimal(0);
            BigDecimal costAmts = new BigDecimal(0);
            BigDecimal costExemptionAmts = new BigDecimal(0);
            BigDecimal dueAmts = new BigDecimal(0);

            for (ManageCostExemptDetailed costExemptDetailed : manageCostExemptDetailedList) {
                //费用总计
                if (costExemptDetailed.getTotalCost() != null) {
                    totalCosts = totalCosts.add(costExemptDetailed.getTotalCost());
                }
                //费用金额
                if (costExemptDetailed.getCostAmt() != null) {
                    costAmts = costAmts.add(costExemptDetailed.getCostAmt());
                }
                //豁免金额
                if (costExemptDetailed.getExemptionAmt() != null) {
                    costExemptionAmts = costExemptionAmts.add(costExemptDetailed.getExemptionAmt());
                }

                //到期金额
                if (costExemptDetailed.getDueAmt() != null) {
                    dueAmts = dueAmts.add(costExemptDetailed.getDueAmt());
                }
            }
            ManageCostExempt manageCostExempt = new ManageCostExempt();

            manageCostExempt.setContractNo(contractNo);
            //数据来源 暂时不知道,
            // manageCostExempt.setDataSource(manageCostExemptDetailedList.get(0).getBusinessSource());
            manageCostExempt.setCustomerName(custName);
            manageCostExempt.setCaseNo(caseNo);
            manageCostExempt.setTotalCost(totalCosts);
            manageCostExempt.setCostAmount(costAmts);
            manageCostExempt.setExemptionAmount(costExemptionAmts);
            manageCostExempt.setAmountDue(dueAmts);
            manageCostExempt.setStatus(ProcessStatusEnum.underReview.toString());


            //到期日
            manageCostExempt.setIsEffect(YesOrNoEnum.yes);
            //费用扣款日,生效日期
            //manageCostExempt.setEffectiveDate(new Date());
            manageCostExempt.setDelFlag("0");
            manageCostExemptService.save(manageCostExempt);

            //保存完汇总之后,开始分条保存信息
            List<BasicExpenseRecordDetailDto> basicExpenseRecordDetailList = new ArrayList<>();
            BasicExpenseRecordDetailDto basicExpenseRecordDetailCondition2 = new BasicExpenseRecordDetailDto();
            for (CostExemptDetailedCondition costExemptDetailed : manageCostExemptDetailedList) {
                costExemptDetailed.setId(null);
                costExemptDetailed.setExemptId(manageCostExempt.getId());
                costExemptDetailed.setApplyDate(new Date());
                costExemptDetailed.setCaseNo(caseNo);
                manageCostExemptDetailedService.save(costExemptDetailed);

                BasicExpenseRecordDetailDto basicExpenseRecordDetailCondition = new BasicExpenseRecordDetailDto();
                basicExpenseRecordDetailCondition.setId(costExemptDetailed.getExpenseDetailId());
                basicExpenseRecordDetailCondition.setContractNo(costExemptDetailed.getContractNo());
                basicExpenseRecordDetailCondition.setCostType(costExemptDetailed.getCostType());
                basicExpenseRecordDetailCondition.setExemptionAmt(costExemptDetailed.getExemptionAmt());
                basicExpenseRecordDetailList.add(basicExpenseRecordDetailCondition);
            }
            basicExpenseRecordDetailCondition2.setBasicExpenseRecordDetailList(basicExpenseRecordDetailList);
            Map<String, String> headers = new HashMap<>();
            headers.put(AfsEnumUtil.key(ContractFeginParamEnum.BASIC_CLIENT_ID), contractFeginConfig.getBasicClientId());
            headers.put(AfsEnumUtil.key(ContractFeginParamEnum.BASIC_CLIENT_SECRET), contractFeginConfig.getBasicClientSecret());
            Assert.isTrue((boolean) basicMainInfoFeign.costExemptApprovel(basicExpenseRecordDetailCondition2, headers).getData(), "提交失败");
        }
        return IResponse.success("提交成功");
    }

    @PostMapping("/submitCostExemptList")
    @ApiOperation(value = "提交费用豁免清单审核")
    @Transactional
    public IResponse submitCostExemptList(@RequestBody List<CostExemptDetailedCondition> conditions) {
        //先汇总保存,然后再分别保存到明细表
        List<CostExemptDetailedCondition> manageCostExemptDetailedList = conditions;
        int size = manageCostExemptDetailedList.size();
        if (manageCostExemptDetailedList.size() > 0) {
            for (int i = size - 1; i >= 0; i--) {
                if (manageCostExemptDetailedList.get(i).getExemptionAmt().compareTo(BigDecimal.ZERO) == 0) {
                    manageCostExemptDetailedList.remove(i);
                }
            }
        }

        if (manageCostExemptDetailedList.size() > 0) {

            for (CostExemptDetailedCondition costExemptDetailedCondition : manageCostExemptDetailedList) {
                BigDecimal totalExemptAmt = costExemptDetailedCondition.getExemptionAmt();
                CostExemptConfigVo quotaLimit = getCostExemptQuotaByUser();
                if (costExemptDetailedCondition.getExemptionAmt().compareTo(quotaLimit.getSingleSurplusAmt()) == 1 && quotaLimit.getSingleLimitSwitch().equals(YesOrNoEnum.yes.toString())) {
                    return IResponse.success("单笔限额为,"+ quotaLimit.getSingleSurplusAmt());
                    //  return IResponse.fail("类型为" + costType.getDesc() + "的费用豁免单笔额度不足,操作失败!该类型的单笔额度为:" + quotaLimit.getSingleSurplusAmt());
                }else if(quotaLimit.getSingleLimitSwitch().equals(YesOrNoEnum.no.toString())){
                    return IResponse.success("无单笔限额");
                }

                for (CostExemptDetailedCondition detailedCondition : manageCostExemptDetailedList) {
                    if (costExemptDetailedCondition.getCostType().equals(detailedCondition.getCostType())) {
                        totalExemptAmt = totalExemptAmt.add(detailedCondition.getExemptionAmt());
                    }
                }
                if (totalExemptAmt.compareTo(quotaLimit.getTotalSurplusAmt()) == 1 && quotaLimit.getTotalLimitSwitch().equals(YesOrNoEnum.yes.toString())) {
                    return IResponse.success("整体限额剩余,"+ quotaLimit.getTotalSurplusAmt());
                    //  return IResponse.fail("类型为" + costType.getDesc() + "的费用豁免本年度总体额度不足,操作失败!该类型本年度总体额度剩余:" + quotaLimit.getTotalSurplusAmt());
                }if(quotaLimit.getTotalLimitSwitch().equals(YesOrNoEnum.no.toString())){
                    return IResponse.success("无整体限额");
                }
            }

            //合同号
            String contractNo = manageCostExemptDetailedList.get(0).getContractNo();
            String custName = manageCostExemptDetailedList.get(0).getCustName();
            String caseNo = CreatCaseNoUtil.GeneratorCaseNo(ContractBusinessEnum.costExempt);

            BigDecimal totalCosts = new BigDecimal(0);
            BigDecimal costAmts = new BigDecimal(0);
            BigDecimal costExemptionAmts = new BigDecimal(0);
            BigDecimal dueAmts = new BigDecimal(0);

            for (ManageCostExemptDetailed costExemptDetailed : manageCostExemptDetailedList) {
                //费用总计
                if (costExemptDetailed.getTotalCost() != null) {
                    totalCosts = totalCosts.add(costExemptDetailed.getTotalCost());
                }
                //费用金额
                if (costExemptDetailed.getCostAmt() != null) {
                    costAmts = costAmts.add(costExemptDetailed.getCostAmt());
                }
                //豁免金额
                if (costExemptDetailed.getExemptionAmt() != null) {
                    costExemptionAmts = costExemptionAmts.add(costExemptDetailed.getExemptionAmt());
                }

                //到期金额
                if (costExemptDetailed.getDueAmt() != null) {
                    dueAmts = dueAmts.add(costExemptDetailed.getDueAmt());
                }
            }

            CostExemptCondition manageCostExempt = new CostExemptCondition();

            //处理人
            manageCostExempt.setProcessPerson(conditions.get(0).getProcessPerson());
            manageCostExempt.setContractNo(contractNo);
            //数据来源 暂时不知道,
            //manageCostExempt.setDataSource(new DataSourceEnum());
            manageCostExempt.setCustomerName(custName);
            manageCostExempt.setCaseNo(caseNo);
            manageCostExempt.setTotalCost(totalCosts);
            manageCostExempt.setCostAmount(costAmts);
            manageCostExempt.setExemptionAmount(costExemptionAmts);
            manageCostExempt.setAmountDue(dueAmts);
            manageCostExempt.setStatus(ProcessStatusEnum.underReview.toString());

            //结束日期,这里不需要填,审核最后一岗再填
            // manageCostExempt.setEndDate(null);
            manageCostExempt.setIsEffect(YesOrNoEnum.no);
            //费用扣款日,生效日期
            //manageCostExempt.setEffectiveDate(new Date());
            manageCostExempt.setDelFlag("0");
            manageCostExemptService.save(manageCostExempt);

            //保存完汇总之后,开始分条保存信息
            List<Long> eIds = new ArrayList<>();
            for (CostExemptDetailedCondition costExemptDetailed : manageCostExemptDetailedList) {
                costExemptDetailed.setId(null);
                costExemptDetailed.setExemptId(manageCostExempt.getId());
                costExemptDetailed.setApplyDate(new Date());
                costExemptDetailed.setCaseNo(caseNo);
                manageCostExemptDetailedService.save(costExemptDetailed);
                eIds.add(costExemptDetailed.getExpenseDetailId());
            }
            //这里需要改basic库中的状态
            Map<String, String> headers = new HashMap<>();
            headers.put(AfsEnumUtil.key(ContractFeginParamEnum.BASIC_CLIENT_ID), contractFeginConfig.getBasicClientId());
            headers.put(AfsEnumUtil.key(ContractFeginParamEnum.BASIC_CLIENT_SECRET), contractFeginConfig.getBasicClientSecret());
            BasicExpenseRecordDetailDto dto = new BasicExpenseRecordDetailDto();
            dto.setExpenseDetailIds(eIds);
            dto.setStatus(ProcessStatusEnum.underReview.toString());
            Assert.isTrue((boolean) basicMainInfoFeign.changeExpenseRecordStatus(dto, headers).getData(), "提交失败");
            //处理完成后开始提交工作流
            submitCostExemptWorkFlow(manageCostExempt);
        }
        return IResponse.success("提交成功");
    }

    /**
     * 提交豁免费用到工作流
     */
    public void submitCostExemptWorkFlow(ManageCostExempt exempt) {

        //拿到在这个流程的数据
        List<ManageCostExemptDetailed> detailedList = manageCostExemptDetailedService.list(Wrappers.<ManageCostExemptDetailed>query().lambda()
                .eq(ManageCostExemptDetailed::getExemptId, exempt.getId())
        );

        if (detailedList.size() > 0) {
            saveApproveInfoProcessor.saveApproveInfo(exempt, ContractBusinessEnum.costExempt,
                    CaseStatusEnum.UNDER_REVIEW, BusinessUrlEnum.COST_EXEMPT);
            StartFlowRequest startFlowRequest = new StartFlowRequest();
            startFlowRequest.setAfsFlowKey(AfsEnumUtil.key(WorkflowTypeEnum.COST_EXEMPT));
            startFlowRequest.setBizDataId(String.valueOf(exempt.getId()));
            startFlowRequest.setFlowName((StringUtils.isEmpty(exempt.getContractNo()) ? "" : (exempt.getContractNo()) + "-") + AfsEnumUtil.desc(WorkflowTypeEnum.COST_EXEMPT));
            String json = JSONObject.toJSONString(exempt);
            JSONObject cancelJson = JSONObject.parseObject(json);
            //保存审批记录
            TaskSubmitVO vo = new TaskSubmitVO();
            vo.setBizData(cancelJson);
            vo.setApprovalOpinion(AfsEnumUtil.desc(NormalSubmitEnum.SUGGEST_CHECK_FINAL));
            workflowSubmitService.saveRecord(vo, AfsEnumUtil.desc(NormalSubmitEnum.SUGGEST_CHECK_FINAL));
            //开始流程
            workflowService.startWorkFlow(startFlowRequest, cancelJson);
        }
    }

    @GetMapping("/delCostExemptInfo/{id}")
    @ApiOperation(value = "删除费用豁免清单")
    public IResponse delCostExemptInfo(@PathVariable Long id) {
        boolean result = false;
        if (id != null) {
            result = manageCostExemptService.removeById(id);
        }
        return result ? IResponse.success("删除成功") : IResponse.fail("删除失败");
    }


    @ApiOperation(value = "根据用户信息获取额度")
    public CostExemptConfigVo getCostExemptQuotaByUser() {

        //费用额度配置中费用类型
        String costType = "cost";
        //获取当前用户
        String username = SecurityUtils.getUsername();
        Long deptId = SecurityUtils.getUser().getDeptId();
        CostExemptConfigVo costExemptConfigVo = new CostExemptConfigVo();
        //查询当前用户该费用类型的单笔限额
        ManageCostExemptConfig oneConfig = manageCostExemptConfigService.getOne(Wrappers.<ManageCostExemptConfig>query().lambda()
                .eq(ManageCostExemptConfig::getUser, username)
                .eq(ManageCostExemptConfig::getCostType, costType)
                .eq(ManageCostExemptConfig::getType, CostExemptTypeEnum.single)
        );
        if (oneConfig != null) {
            costExemptConfigVo.setSingleSurplusAmt(oneConfig.getLimitAmt());
            costExemptConfigVo.setSingleLimitSwitch(YesOrNoEnum.yes.toString());
        } else {
            costExemptConfigVo.setSingleSurplusAmt(BigDecimal.ZERO);
            costExemptConfigVo.setSingleLimitSwitch(YesOrNoEnum.no.toString());
        }
        //总体限额
        String year = new SimpleDateFormat("yyyy").format(new Date());
        ManageCostExemptConfig totalConfig = manageCostExemptConfigService.getOne(Wrappers.<ManageCostExemptConfig>query().lambda()
                .eq(ManageCostExemptConfig::getDeptId, deptId)
                .eq(ManageCostExemptConfig::getCostType, costType)
                .eq(ManageCostExemptConfig::getType, CostExemptTypeEnum.total)
                .eq(ManageCostExemptConfig::getYear, year)
        );
        if (totalConfig != null) {
            costExemptConfigVo.setTotalSurplusAmt(totalConfig.getSurplusLimitAmt());
            costExemptConfigVo.setTotalLimitSwitch(YesOrNoEnum.yes.toString());
        } else {
            costExemptConfigVo.setTotalSurplusAmt(BigDecimal.ZERO);
            costExemptConfigVo.setTotalLimitSwitch(YesOrNoEnum.no.toString());
        }
        return costExemptConfigVo;
    }

}
